#ifndef BufferedVMEReader_h
#define BufferedVMEReader_h

#include "sys/types.h"
#include "FIFO32DMAReader.h"
#include <iostream>

class BufferedVMEReader
{
 private:
    u_int32_t cell_size;            //size of one cell in words
    u_int32_t cell_no;              //number of cells
    u_int32_t *buffer, buffer_size;
    u_int32_t put_index;
    u_int32_t get_index;
    FIFO32DMAReader *f32dr;

 public:
    BufferedVMEReader(u_int32_t cell_size, u_int32_t cell_no,
		      FIFO32DMAReader *f32dr)
    {
	this->cell_size = cell_size;
	this->cell_no   = cell_no;
	this->f32dr     = f32dr;

	buffer_size     = cell_size*cell_no;
	buffer          = new u_int32_t[buffer_size];
	put_index       = 0;
	get_index       = 0;
    };

    u_int32_t read(u_int32_t len, u_int32_t *buf)
    {
	for(u_int32_t i=0; i < len; i++) {
	    if(wordsInBuffer()==0) {
//		std::cout << "BufferedVMEReader::read(): reload" << std::endl;
		f32dr->readFIFO32DMA(cell_size,buffer + put_index);
		put_index += cell_size;
		if(put_index > buffer_size - cell_size) 
		    put_index = 0;
	    }

	    buf[i] = buffer[get_index];
	    get_index++;
	    if(get_index >= buffer_size) get_index=0;	    
	}
	return 0;
    }

    u_int32_t readWord()
    {
	if(wordsInBuffer()==0) {
//	    std::cout << "BufferedVMEReader::read(): reload" << std::endl;
	    f32dr->readFIFO32DMA(cell_size,buffer + put_index);
	    put_index += cell_size;
	    if(put_index > buffer_size - cell_size) 
		put_index = 0;
	}

	u_int32_t r=buffer[get_index];
	get_index++;
	if(get_index >= buffer_size) get_index=0;	    

	return r;
    }

    u_int32_t wordsInBuffer()
    {
	if(put_index >= get_index)
	    return (put_index - get_index);
	else
	    return (buffer_size - get_index + put_index);
    }
};

#endif
